package cn.hwadee.muying.commons.base;

import cn.hwadee.muying.commons.utils.DateTools;
import com.baomidou.mybatisplus.enums.SqlMethod;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.toolkit.CollectionUtils;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.session.SqlSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.sql.Timestamp;
import java.util.List;

/**
 * @描述: 重新封装Mybatis-Plus的业务处理基类，填充公共字段
 * @作者: Pengo.Wen
 * @日期: 2017-05-25 15:15
 * @版本: v1.0
 */
public class BaseService<M extends BaseMapper<T>, T extends BaseModel> extends ServiceImpl<M, T> {

    protected final Logger log = LoggerFactory.getLogger(this.getClass());

    protected void initEntity(T entity){
        Timestamp currentTime= DateTools.getTime();
        if(entity.getId() != null && entity.getId() > 0){
            entity.setUpdateDate(currentTime);
        }else{
            entity.setCreateDate(currentTime);
            entity.setUpdateDate(currentTime);
            entity.setValid(true);
        }
    }

    @Override
    public boolean insert(T entity) throws RuntimeException{
        initEntity(entity);
        return super.insert(entity);
    }

    @Override
    public boolean insertBatch(List<T> entityList) throws RuntimeException {
        entityList.forEach(this::initEntity);
        return super.insertBatch(entityList);
    }

    @Override
    public boolean insertBatch(List<T> entityList, int batchSize) throws RuntimeException {
        if (CollectionUtils.isEmpty(entityList)) {
            return false;
        }
        entityList.forEach(this::initEntity);
        return super.insertBatch(entityList, batchSize);
    }

    @Override
    public boolean insertOrUpdate(T entity)  throws RuntimeException {
        initEntity(entity);
        return super.insertOrUpdate(entity);
    }

    @Override
    public boolean insertOrUpdateBatch(List<T> entityList)  throws RuntimeException {
        entityList.forEach(this::initEntity);
        return super.insertOrUpdateBatch(entityList);
    }

    @Override
    public boolean insertOrUpdateBatch(List<T> entityList, int batchSize)  throws RuntimeException {
        entityList.forEach(this::initEntity);
        return super.insertOrUpdateBatch(entityList, batchSize);
    }

    @Override
    public boolean deleteById(Serializable id) throws RuntimeException {
        T entity = selectById(id);
        return delete(entity);
    }

    public boolean delete(T entity) throws RuntimeException{
        Timestamp currentTime=DateTools.getTime();
        if(null != entity){
            entity.setDeleteDate(currentTime);
            entity.setValid(false);
            return updateById(entity);
        }else {
            return false;
        }
    }

    @Override
    public T selectById(Serializable id) {
        return super.selectById(id);
    }


    @Override
    public int selectCount(Wrapper<T> wrapper) {
        return super.selectCount(wrapper);
    }

    @Override
    public boolean updateById(T entity) throws RuntimeException {
        Timestamp currentTime=DateTools.getTime();
        entity.setUpdateDate(currentTime);
        //因为乐观锁导致更新不成功，则抛出异常
        boolean result = super.updateAllColumnById(entity);
        if(result == true){
            return result;
        }else{
            throw new RuntimeException("更新失败，该实体对象非最新状态，请重新加载！");
        }
    }

    @Override
    public boolean updateBatchById(List<T> entityList, int batchSize) {
            if (CollectionUtils.isEmpty(entityList)) {
                throw new IllegalArgumentException("Error: entityList must not be empty");
            }
            try (SqlSession batchSqlSession = sqlSessionBatch()) {
                int size = entityList.size();
                String sqlStatement = sqlStatement(SqlMethod.UPDATE_ALL_COLUMN_BY_ID);
                Timestamp updateTime = DateTools.getTime();
                for (int i = 0; i < size; i++) {
                    T entity = entityList.get(i);
                    entity.setUpdateDate(updateTime);
                    MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap();
                    param.put("et", entity);
                    batchSqlSession.update(sqlStatement, param);
                    if (i >= 1 && i % batchSize == 0) {
                        batchSqlSession.flushStatements();
                    }
                }
                batchSqlSession.flushStatements();
            } catch (Exception e) {
                log.error("Error: Cannot execute insertBatch Method. Cause:" + e);
                return false;
            }
            return true;
    }
}
